﻿#ifndef QLIB_HEADER_DB
#define QLIB_HEADER_DB

#include <assert.h>
#include <errno.h>
#include <iostream>
#include <set>
#include <string>

// #include "rapidjson/document.h"
// #include "rapidjson/stringbuffer.h"
// #include "rapidjson/writer.h"

#include <spdlog/spdlog.h>
#include <nlohmann/json.hpp>

#include "qlib/core/error.h"
#include "qlib/core/object.h"
#include "qlib/core/vec2.h"
#include "qlib/db/gdsii.h"
#include "qlib/db/oasis.h"
#include "qlib/layout/cell.h"
#include "qlib/layout/library.h"

namespace qlib {

using json = nlohmann::json;

struct ByteArray {
  uint64_t count;
  uint8_t* bytes;
  PropertyArray* properties;

  std::string name;
  PropertyArray property_arr;
};

struct StringArray {
  std::string name;
  PropertyArray properties;
};

class QLIB_API DB {
 public:
  DB();
  ~DB();

  // gds
  static Library::s_ptr read_gds(std::string filename, double unit, double tolerance, ErrorCode* error_code);
  static ErrorCode write_gds(const Library::s_ptr library, std::string filename, uint64_t max_points, tm* timestamp);
  static ErrorCode write_gds(const PropertyArray& properties, FILE* out);
  static ErrorCode write_gds(const Polygon::s_ptr poly, FILE* out, double scaling);
  static ErrorCode write_gds(const Label::s_ptr label, FILE* out, double scaling);
  static ErrorCode write_gds(const Pin::s_ptr pin, FILE* out, double scaling);
  static ErrorCode write_gds(const KeyPoint::s_ptr keyPoint, FILE* out, double scaling);
  static ErrorCode write_gds(const Text::s_ptr text, FILE* out, double scaling);

  static ErrorCode write_gds(const Path::s_ptr line, FILE* out, double scaling);
  static ErrorCode write_gds(const Reference::s_ptr refer, FILE* out, double scaling);
  static ErrorCode write_gds(const Cell::s_ptr cell, FILE* out, double scaling, uint64_t max_points, double precision, const tm* timestamp);

  // oas
  static Library::s_ptr read_oas(const std::string& filename, double unit, double tolerance, ErrorCode* error_code);
  // 写入oas
  static ErrorCode properties_to_oas(PropertyArray& properties, OasisStream& out, OasisState& state);
  static ErrorCode rectangle_to_oas(Rectangle::s_ptr rectangle, OasisStream& out, OasisState& state);
  static ErrorCode circle_to_oas(Circle::s_ptr circle, OasisStream& out, OasisState& state);
  static ErrorCode ellipse_to_oas(Ellipse::s_ptr circle, OasisStream& out, OasisState& state);
  static ErrorCode fan_to_oas(Fan::s_ptr circle, OasisStream& out, OasisState& state);
  static ErrorCode polygon_to_oas(Polygon::s_ptr polygon, OasisStream& out, OasisState& state);
  static ErrorCode path_to_oas(Path::s_ptr path, OasisStream& out, OasisState& state);
  static ErrorCode label_to_oas(Label::s_ptr label, std::unordered_map<std::string, uint64_t>& text_string_map, OasisStream& out, OasisState& state);
  static ErrorCode text_to_oas(Text::s_ptr label, std::unordered_map<std::string, uint64_t>& text_string_map, OasisStream& out, OasisState& state);
  static ErrorCode pin_to_oas(Pin::s_ptr label, std::unordered_map<std::string, uint64_t>& text_string_map, OasisStream& out, OasisState& state);
  static ErrorCode keypoint_to_oas(KeyPoint::s_ptr label, std::unordered_map<std::string, uint64_t>& text_string_map, OasisStream& out,
                                   OasisState& state);
  static ErrorCode reference_to_oas(Reference::s_ptr ref, std::unordered_map<std::string, uint64_t>& cell_name_map, OasisStream& out,
                                    OasisState& state);
  // oas自定义几何
  // static ErrorCode text_to_oas(Text::s_ptr text, OasisStream& out, OasisState& state);
  // static ErrorCode ellipse_to_oas(Ellipse::s_ptr ellipse, OasisStream& out, OasisState& state);
  // static ErrorCode fan_to_oas(Fan::s_ptr fan, OasisStream& out, OasisState& state);
  static ErrorCode ruler_to_oas(Ruler::s_ptr ruler, OasisStream& out, OasisState& state);
  static ErrorCode write_oas(Library::s_ptr library, const std::string& filename, uint8_t compression_level = 6, bool detect_rectangles = true,
                             bool detect_trapezoids = true, double circle_tolerance = 0, double standard_properties = false,
                             OasisValidationType validation = OasisValidationType::NONE);
  // svg
  static ErrorCode write_svg(const Cell::s_ptr cell, std::string filename, double scaling, uint32_t precision, std::string background, double pad,
                             bool pad_as_percentage);
  static ErrorCode write_svg(const Polygon::s_ptr poly, FILE* out, double scaling, uint32_t precision);
  static ErrorCode write_svg(const Label::s_ptr label, FILE* out, double scaling, uint32_t precision);
  static ErrorCode write_svg(const Path::s_ptr path, FILE* out, double scaling, uint32_t precision);
  static ErrorCode write_svg(const Reference::s_ptr reference, FILE* out, double scaling, uint32_t precision);
  static ErrorCode write_svg(const Cell::s_ptr cell, FILE* out, double scaling, uint32_t precision, std::string attributes);
};

}  // namespace qlib

#endif